package com.kamistoat.ruoyi.ruoyimodulessystem.controller;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kamistoat.ruoyi.ruoyiapisystem.domain.SysUserOnline;
import com.kamistoat.ruoyi.ruoyiapisystem.entity.SysUserEntity;
import com.kamistoat.ruoyi.ruoyicommoncore.constant.CacheConstants;
import com.kamistoat.ruoyi.ruoyicommoncore.constant.Constants;
import com.kamistoat.ruoyi.ruoyicommoncore.utils.StringUtils;
import com.kamistoat.ruoyi.ruoyicommoncore.web.controller.BaseController;
import com.kamistoat.ruoyi.ruoyicommoncore.web.domain.AjaxResult;
import com.kamistoat.ruoyi.ruoyicommoncore.web.page.TableDataInfo;
import com.kamistoat.ruoyi.ruoyicommonlog.annotation.Log;
import com.kamistoat.ruoyi.ruoyicommonlog.enums.BusinessType;
import com.kamistoat.ruoyi.ruoyicommonredis.utils.RedissonUtils;
import com.kamistoat.ruoyi.ruoyicommonsecurity.annotation.RequiresPermissions;
import com.kamistoat.ruoyi.ruoyicommonsecurity.utils.TokenUtils;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysUserService;
import com.kamistoat.ruoyi.ruoyimodulessystem.service.SysUserOnlineService;
import org.redisson.api.RMapCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 在线用户监控。原项目实现的有问题。
 * 原项目是直接将所有 后端登录令牌 的用户作为在线用户。显然这根本不对，因为这样统计的是 允许自动登录的用户。
 * 我们还是采用在每次请求到达被网关处理时，根据jwtToken更新在线用户表单，
 * <p>
 * Redisson提供 RMapCache可以很方便的实现这一功能。
 * Map中一个元素代表一个在线记录。使用 CacheConstants.ONLINE_USER_KEY + userId + ":" + ipaddr + ":" + userKey;
 * <p>
 * 后来还是改回使用普通k-v了，而且实际上这个功能用该使用ElasticSearch来做，因为redis对模糊/批查询支持度很差
 */
@RestController
@RequestMapping("/online")
public class SysUserOnlineController extends BaseController {
    @Autowired
    SysUserOnlineService sysUserOnlineService;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    RedissonUtils redissonUtils;
    @Autowired
    TokenUtils tokenUtils;

    /**
     * 获取当前在线用户列表
     */
    @RequiresPermissions("monitor:online:list")
    @GetMapping("/list")
    public TableDataInfo list(String ipaddr, String userName) {
        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
//        RMapCache<String, String> onlineRMapCache = redissonUtils.getRedissonClient().
//                getMapCache(CacheConstants.ONLINE_USER_KEY + "RMapCache");
//
//        // 若未输入条件查询，则默认返回最近200个在线用户
//        // 能不用匹配就不用匹配。慢
//        if (StringUtils.isEmpty(ipaddr) && StringUtils.isEmpty(userName)) {
//            Collection<String> values = onlineRMapCache.values(200);
//            for (String value : values) {
//                SysUserOnline sysUserOnline = JSON.parseObject(value, SysUserOnline.class);
//                userOnlineList.add(sysUserOnline);
//            }
//        } else {
//            // 若携带了查询条件，则只能用匹配查询
//            String userIdPattern = "*";
//            if (StringUtils.isNotEmpty(userName)) {
//                SysUserEntity one = sysUserService.getOne(new QueryWrapper<SysUserEntity>().select("user_id").eq("user_name", userName));
//                userIdPattern = StringUtils.isNull(one) ? userIdPattern : one.getUserId().toString();
//            }
//            String ipPattern = StringUtils.isEmpty(ipaddr) ? "*" : ipaddr;
//            String pattern = CacheConstants.ONLINE_USER_KEY + userIdPattern + ":" + ipPattern + ":*";
//            Set<String> keySet = onlineRMapCache.keySet(pattern);
//            Collection<String> values = onlineRMapCache.getAll(keySet).values();
//            for (String value : values) {
//                SysUserOnline sysUserOnline = JSON.parseObject(value, SysUserOnline.class);
//                userOnlineList.add(sysUserOnline);
//            }
//        }
        if (StringUtils.isEmpty(ipaddr) && StringUtils.isEmpty(userName)) {
            Collection<String> keys = redissonUtils.keys(CacheConstants.ONLINE_USER_KEY + "*");
            for (String key : keys) {
                Object cacheObject = redissonUtils.getCacheObject(key);
                if (cacheObject != null) {
                    userOnlineList.add(JSON.parseObject(String.valueOf(cacheObject), SysUserOnline.class));
                }
            }
        } else {
            String userIdPattern = "*";
            if (StringUtils.isNotEmpty(userName)) {
                SysUserEntity one = sysUserService.getOne(new QueryWrapper<SysUserEntity>().select("user_id").eq("user_name", userName));
                userIdPattern = StringUtils.isNull(one) ? userIdPattern : one.getUserId().toString();
            }
            String pattern = CacheConstants.ONLINE_USER_KEY + userIdPattern + ":*";
            Collection<String> keys = redissonUtils.keys(pattern);
            for (String key : keys) {
                Object cacheObject = redissonUtils.getCacheObject(key);
                if (cacheObject != null) {
                    userOnlineList.add(JSON.parseObject(String.valueOf(cacheObject), SysUserOnline.class));
                }
            }
        }
        return getDataTable(userOnlineList);
    }

    /**
     * 强退用户.不仅强退在线状态，同时删除 后端登录令牌 和 核心信息令牌
     */
    @RequiresPermissions("monitor:online:forceLogout")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/forceLogout")
    public AjaxResult forceLogout(@RequestParam String tokenId, @RequestParam Long userId) {
        // 删除在线状态
        redissonUtils.deleteObject(CacheConstants.ONLINE_USER_KEY + userId + ":" + tokenId);
        // 删除后端登录令牌
        redissonUtils.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + userId + ":" + tokenId);
        // 删除后端核心令牌
        redissonUtils.deleteObject(CacheConstants.USER_CORE_KEY + userId);
        // 前端有问题，要改得全改，这里就先不实现了
        return AjaxResult.success();
    }

}
